/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Client;

import Module.ActionList;
import Module.ResourceProject;
import Module.Project;
import Module.Session;
import Module.Team;
import Module.User;
import Module.Activity;
import Module.ChattLog;
import Module.DecisionList;
import Module.Resource;
import Module.ResourceType;
import Module.Role;
import Module.addUserRoles;
import Shared.Callback;
import Shared.Server;
import View.*;
import java.awt.AWTException;
import java.awt.Image;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.util.logging.*;
import javax.swing.JFrame.*;
import java.net.MalformedURLException;
import java.rmi.*;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.Unreferenced;
import java.text.ParseException;
import java.util.ArrayList;
import javax.swing.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Properties;
/**
 *
 * @author CCD gruppe 2
 * This is the client which gets the reference to the remote object and invokes its methods
 *
 */
public class Client {

    static String ip;
    private Server server;
    private String clientIp;
    private Login loginn;
    private ArrayList<Module.Session> sessions = new ArrayList<Module.Session>();
    private ArrayList<Module.Activity> activities;
    private int selectedSessionTab;
    ArrayList<Module.User> leaders = new ArrayList<Module.User>();
    DefaultComboBoxModel leadersBox = new DefaultComboBoxModel();
    ArrayList<DefaultComboBoxModel> facilitatorModelList;
    ArrayList<DefaultComboBoxModel> secretaryModelList;
    ArrayList<DefaultComboBoxModel> placesModelList;
    ArrayList<DefaultListModel> availableUserListModel;
    ArrayList<DefaultListModel> addedUserListModel;
    int aktivitetsId;
    int panelNr = 0;
    int activityNumber;
    private Callback callback;
    private boolean logginButton = false;
    private ArrayList<Module.Project> projects;
    private ArrayList<Module.User> projectUsers;
    private ArrayList<String> projectNames = new ArrayList<String>();
    private Module.Session selectedSession;
    private Module.Project selectedProject = new Project();
    private Module.Activity selectedActivity;
    private GUI gui;
    private boolean admin;
    private User user;


    public Client() {
        try {
            readProperties();
            run();

        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public void run() throws RemoteException {
        gui = new GUI(this);

        try {
            try {
                InetAddress thisIp = InetAddress.getLocalHost();
                clientIp = thisIp.getHostAddress();
                thisIp = InetAddress.getByName(clientIp);

            } catch (java.net.UnknownHostException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
            //System.out.println("FØR LOOKUP " +getIp());

            server = (Server) Naming.lookup(getNaming());
            loginn = new Login(gui, server);
            logginButton = false;
            while (!logginButton) {
                logginButton = loginn.isState();
            }
            callback = new CallbackImpl();
            callback.setTextArea(gui.getChatPanel().getTextAreaMainChat());
            server.connect(callback,ip);
            user = server.getUserForUsername(loginn.getUsername());
            callback.setUserName(user.getFullname());
            ArrayList<String> role = server.getRoleToUser(server.getUserForUsername(loginn.getUsername()).getId());
            admin=false;
            for(int i=0; i<role.size();i++){
                if(role.get(i).equals("Administrator")){
                    admin=true;
                    break;
                }
            }
            projects = server.getAllProjectsToUser(loginn.getUsername());
            gui.setUserName(user.getFullname());
            gui.welcomeTabInsertData();
            gui.setUpUserAdminMenu();
            updateProjectList();
            


        } catch (NotBoundException bound) {
            System.out.println("Error: Not bound exception\n" + bound);
        } catch (MalformedURLException url) {
            System.out.println("Error: No RMI register located on" + server + "\nErrormessage" + url);
        } catch (RemoteException re) {
            System.out.println("Error: Something went wrong remotely\n" +getNaming() +" exception" + re);
        }


        Runtime.getRuntime().addShutdownHook(new Thread() {
             public void run() {
                try {
                    server.quit(callback,clientIp);
                } catch (RemoteException ex) {
                    Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                }
             }
                });
    }


    public static void main(String[] args) throws Exception {

        new Client();
       
    }

    public String getClientIp() {
        return clientIp;
    }


    /**
     * A method that reads the properties file
     */
    public void readProperties() {
        Properties appProperties = new Properties();
        try {
            String path = System.getProperty("user.dir");
            // load the properties file onto Properties object.
            System.out.println(path);
            appProperties.load(new FileInputStream(path + "/settings.properties"));
            // access ur properties
            String IP = (String) appProperties.get("ip");
            //String portNumber = (String) appProperties.get("DB.portnumber");
            ip = IP;
            System.out.println("SERVERIP: " + ip);
        } catch (IOException e) {
        }
    }

    /**
     * A method that tries to update the connection to server
     */
    public void updateServer() {
        server = null;
        try {
            server = (Server) Naming.lookup(getNaming());
        } catch (NotBoundException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        } catch (MalformedURLException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }



    }

    /**
     * A method that gets the naming of the register
     * @return
     */
    public static String getNaming() {
        return "rmi://" + ip +"/ServerImpl";
    }
    /**
     * This is a method that return the session that is nearest to todays date
     * @return Session
     */
    public Session findNearestSession() {
        //yyyymmdd
        int todaysdate = 0;
        Calendar currenDate = Calendar.getInstance();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String dato = dateFormat.format(currenDate.getTime());
        todaysdate = Integer.parseInt(dato.replaceAll("-", ""));
        ArrayList<Session> allSessionsForAllProjects = new ArrayList<Session>();
        try {
            allSessionsForAllProjects = server.getAlleSessionsToUser(server.getUserForUsername(loginn.getUsername()).getId());
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        Session session = new Session(0);
        int sessionDate = 0;
        int difference = 99999;
        for (int i = 0; i < allSessionsForAllProjects.size(); i++) {
            sessionDate = Integer.parseInt(allSessionsForAllProjects.get(i).getDate().replaceAll("-", ""));
            if (sessionDate - todaysdate >= 0) {
                //First session tempsaves this
                if (i == 0) {
                    difference = sessionDate - todaysdate;
                    session = allSessionsForAllProjects.get(i);
                } else if (sessionDate - todaysdate < difference) {
                    difference = sessionDate - todaysdate;
                    session = allSessionsForAllProjects.get(i);
                }

            }
        }
        return session;
    }

    /**
     * Method that returns all projects
     * @return all projects
     */
    public ArrayList<Project> getAllProjects() {
        return projects;
    }

    /**
     * Method that returns how many sessions there is to a project
     * @return sessions size
     */
    public int getNumberOfSessions() {
        return sessions.size();
    }

    /**
     * Method that creates an activity
     * @param activityName
     * @param startDate
     * @param endDate
     * @param responsible
     * @param status
     * @param description
     * @param goals
     * @param location
     * @param onActionList
     */
    public void createActivity(String activityName, String startDate, String endDate, String responsible, String status, String description,
            String goals, String location, boolean onActionList) {
        try {
            server.registerActivity(selectedProject.getId(), activityName, startDate, endDate, responsible, status, description, goals,
                    location, onActionList);

            updateActivityList();
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Mehod that edits an activity
     * @param activityName
     * @param startDate
     * @param endDate
     * @param responsible
     * @param status
     * @param description
     * @param goals
     * @param location
     * @param onActionList
     */
    public void editActivity(String activityName, String startDate, String endDate, String responsible, String status, String description,
            String goals, String location, boolean onActionList) {
        try {
            server.editActivity(selectedActivity.getId(), selectedProject.getId(), activityName, startDate, endDate, responsible,
                    status, description, goals, location, onActionList);

            updateActivityList();
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /** Method that deletes the seleceted activity
     *
     */
    public void deleteActivity() {
        try {
            server.deleteActivity(selectedActivity.getId());
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        updateActivityList();
    }
    /**
     * Method that updates the activitylist. used if someone else adds/edit/delete an activity
     */
    public void updateActivityList() {
        try {
            activities = server.getAllActivities(selectedProject.getId());
            gui.updateActivityList();
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method that registers users to a session with role and team
     * @param sessionId
     * @param users
     * @param roleId
     * @param teamId
     */
    public void registerUserToSession(int sessionId, ArrayList<User> users, int roleId, int teamId) {
        try {
            server.registerUserToSession(sessionId, users, roleId, teamId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     *
     * @return sessionName
     */
    public String getSessionBoundToActivity() {
        String sessionDate;
        String sessionName = "";
        if (!sessions.isEmpty()) {
            for (int i = 0; i < sessions.size(); i++) {
                sessionDate = sessions.get(i).getDate();
                if (sessionDate.equals(selectedActivity.getStarteDate()) && sessionDate.equals(selectedActivity.getEndDate())) {
                    sessionName = sessions.get(i).getName();
                    return sessionName;
                }
            }
        }
        return "Ingen tilknytning";
    }
    /**
     * Method used to return all plases a session can take place
     * @return
     */
    public ArrayList<String> getAllPlaces(){
        try {
            return server.getAllPlaces();
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new ArrayList<String>();
    }
    /**
     * Method that returns alle activities to a project
     * @return
     */
    public ArrayList<Activity> getActivitiesForSelectedProject() {
        try {
            activities = server.getAllActivities(selectedProject.getId());
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return activities;
    }
    /**
     * Method that returns all sessions names
     * @return
     */
    public ArrayList<String> getAllSessionNames() {
        ArrayList<String> sessionNames = new ArrayList<String>();

        for (int i = 0; i < sessions.size(); i++) {
            sessionNames.add(sessions.get(i).getName());
        }
        return sessionNames;
    }
    /**
     * Method that returns all sessions to all project
     * @return
     */
    public ArrayList<Session> getAllSessionsForAllProjects() {
        ArrayList<Session> allSessionsForProject;
        ArrayList<Session> totalSessions = new ArrayList<Session>();
        for (Project p : projects) {
            try {
                allSessionsForProject = server.getAllSessionsToProject(p.getId());
                for (int i = 0; i < allSessionsForProject.size(); i++) {
                    totalSessions.add(allSessionsForProject.get(i));
                }
            } catch (RemoteException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return totalSessions;
    }
    /**
     * Method to create a user
     * @param workplace
     * @param fullname
     * @param expertise
     * @param username
     * @return the created user
     */
    public User createUser(String workplace, String fullname, String expertise, String username) {
        try {
            return server.registerUser(workplace, fullname, expertise, username);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new User(0, "", "", "", "", "");
    }
    /**
     * Method to create a tema
     * @param name
     * @return teamID
     */
    public int createTeam(String name) {
        try {
            return server.registerTeam(name);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return 0;
    }
    /**
     * Method to edit a team
     * @param id
     * @param name
     */
    public void editTeam(int id, String name) {
        try {
            server.editTeam(id, name);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method to create a session
     * @param projectId
     * @param sessionName
     * @param date
     * @param place
     * @param startTime
     * @param endTime
     * @param evaluation
     * @param preparation
     * @return sessionId, 0 if there was an error
     */
    public int createSession(int projectId, String sessionName, String date, String place,
            String startTime, String endTime, String evaluation, String preparation) {
        try {
            return server.registerSession(sessionName, date, place, projectId, startTime, endTime, evaluation, preparation);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        updateSessionList();
        return 0;
    }
    /**
     * Method to edit a sessions
     * @param Session
     */
    public void editSession(Session s) {
        try {
            server.editSession(s.getId(), s.getProjectId(), s.getName(), s.getDate(), s.getPlace(), s.getStartTime(), s.getEndTime(), s.getEvaluation(), s.getPreparation());
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
    /**
     * Method to edit the introduction on the Decisionlist page
     * @param projectId
     * @param intro
     */
    public void editDecionListIntro(int projectId, String intro) {
        try {
            server.editDecionListIntro(projectId, intro);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method to get the decisionlistintro
     * @param projectId
     * @return
     */
    public String getDecisionListIntro(int projectId) {
        try {
            return server.getDecisionListIntro(projectId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "";
    }
    /**
     * Method to edit the introduction on the Actionlist page
     * @param projectId
     * @param intro
     */
    public void editActionListIntro(int projectId, String intro) {
        try {
            server.editActionListIntro(projectId, intro);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method to get the action
     * @param projectId
     * @return
     */
    public String getActionListIntro(int projectId) {
        try {
            return server.getActionListIntro(projectId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "";
    }
    /**
     * Method that edits the sessiongoals and sessiondelivery to a team
     * @param teamId
     * @param sessionId
     * @param goal
     * @param delivery
     */
    public void editTeamSession(int teamId, int sessionId, String goal, String delivery) {
        try {
            server.editTeamSession(teamId, sessionId, goal, delivery);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method that removes users to a session
     * @param sessionId
     */
    public void removeUsersFromSession(int sessionId) {
        try {
            server.removeUsersFromSession(sessionId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method that deletes a session
     * @param session
     */
    public void deleteSession(Session session) {
        try {
            sessions.remove(session);
            server.deleteSession(session.getId());
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method that create team goals and team delivery to a session
     * @param teamId
     * @param sessionId
     * @param teamGoal
     * @param teamDelivery
     */
    public void createteamSession(int teamId, int sessionId, String teamGoal, String teamDelivery) {
        try {
            server.registerTeamSession(teamId, sessionId, teamGoal, teamDelivery);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method that gets all teaminfo to a session
     * @param sessionId
     * @return
     */
    public ArrayList<Team> getTeamInfoToSession(int sessionId) {
        try {
            return server.getTeamInfoToSession(sessionId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
    /**
     * Method that returns all teams to a project
     * @param projectId
     * @return
     */
    public ArrayList<Team> getTeamsToProject(int projectId) {
        try {
            return server.getTeamsToProject(projectId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new ArrayList<Team>();
    }
    /**
     * Method that returns all users to a team
     * @param teamID
     * @return
     */
    public ArrayList<User> getUsersToTeam(int teamID) {
        try {
            return server.getUsersToTeam(teamID);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new ArrayList<User>();
    }
    /**
     * Method that returns the user object to a username
     * @param username
     * @return
     */
    public User getUserToUsername(String username) {
        try {
            return server.getUserForUsername(username);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
    /**
     * Method to edit a user roles
     * @param user
     * @param rolle
     */
    public void editUser(User u, ArrayList<String> rolle) {
        try {
            server.editUser(u);
            server.registerRoleToUser(u.getId(), rolle);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method to edit a userinformation
     * @param user
     * @param fullName
     * @param expertise
     * @param workplace
     */
    public void editUserInfo(User u, String fullName, String expertise, String workplace) {
        try {
            server.editUserInfo(u, fullName, expertise, workplace);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method to edit the actionlist
     * @param liste
     */
    public void editActionList(ArrayList<ActionList> liste) {
        try {
            server.editActionList(liste);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method to get the actionlist to a selected project
     * @param projectId
     * @return the actionlist
     */
    public ArrayList<ActionList> getActionListToProject(int projectId) {
        try {
            return server.getActionListToProject(projectId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new ArrayList<ActionList>();
    }
    /**
     * Method to get the decionlist to a selected project
     * @param projectId
     * @return
     */
    public ArrayList<DecisionList> getDecisionListToProject(int projectId) {
        try {
            ArrayList<DecisionList> liste = new ArrayList<DecisionList>();
            liste = server.getDecisionListToProject(projectId);
            return liste;
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new ArrayList<DecisionList>();
    }
    /**
     * Method to check if the password is correct
     * @param password
     * @param username
     * @return
     */
    public boolean isCorrectPassword(String password, String username) {
        try {
            return server.isCorrectPassword(username, password);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }
    /**
     * Method that creates a project
     * @param name
     * @param description
     * @param goals
     * @param projectLeader
     * @returns the projectId
     */
    public int createProject(String name, String description, String goals, String projectLeader) {
        try {
            return server.registerProject(name, description, goals, projectLeader);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return 0;
    }
    /**
     * Method that edit a project
     * @param id
     * @param name
     * @param description
     * @param goals
     * @param projectLeader
     */
    public void editProject(int id, String name, String description, String goals, String projectLeader) {
        try {
            server.editProject(id, name, description, goals, projectLeader);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method to add a user to the voicelist
     * @param projectId
     * @param userId
     */
    public boolean insertIntoVoiceList(int projectId, int userId) {
        try {
             return server.insertIntoVoiceList(projectId, userId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }
    /**
     * Method that remoces a user from the voicelist
     * @param projectId
     * @param userId
     */
    public void removeFromVoiceList(int projectId, int userId) {
        try {
            server.removeFromVoiceList(projectId, userId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method that return the voicelist to a project. Used if the fasilitator presses the remove all button
     * @param projectId
     */
    public void removeVoiceList(int projectId) {
        try {
            server.removeVoiceList(projectId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method that register users to a project
     * @param projectId
     * @param projectUsers
     * @param teamId
     * @param roleId
     */
    public void registerUserToProject(int projectId, ArrayList<User> projectUsers, int teamId, int roleId) {
        try {
            server.registerUserToProject(projectId, projectUsers, teamId, roleId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method that gets what roles a user has in the project
     * @param projectId
     * @param teamId
     * @return
     */
    public ArrayList<addUserRoles> getUserRolesProject(int projectId, int teamId) {
        try {
            return server.getUserRolesProject(projectId, teamId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new ArrayList<addUserRoles>();
    }
    /**
     * Method that register the resourcetype
     * @param name
     * @return
     * @throws RemoteException
     */
    public int registerResourceType(String name) throws RemoteException {
        return server.registerResourceType(name);
    }
    /**
     * Method that register a resource
     * @param resourceName
     * @param resourceTypeName
     * @param resourceTypeId
     * @returns int array whit resourceTypeId in [0] and resourceId in [1]
     * @throws RemoteException
     */
    public int[] registerResource(String resourceName, String resourceTypeName, int resourceTypeId) throws RemoteException {
        return server.registerResource(resourceName, resourceTypeName, resourceTypeId);
    }
    /**
     * Method that gets all resourcetypes
     * @return
     * @throws RemoteException
     */
    public ArrayList<ResourceType> getAllResourceTypes() throws RemoteException {
        return server.getAllResourceType();
    }
    /**
     * Method that returns all the resources
     * @return
     * @throws RemoteException
     */
    public ArrayList<Resource> getAllResource() throws RemoteException {
        return server.getAllResources();
    }
    /**
     * Method to register a resource to a project
     * @param resources
     * @return
     */
    public String registerResourceToProject(ResourceProject resources) {
        try {
            return server.registerResourceToProject(resources);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "";
    }
    /**
     * Method to delete a resource from a project
     * @param projectId
     * @param resourceId
     */
    public void deleteResourceToProject(int projectId, int resourceId) {
        try {
            server.deleteResourceToProject(projectId, resourceId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method to get all resource to a project
     * @param projectId
     * @return
     */
    public ArrayList<ResourceProject> getAllResourceToProject(int projectId) {
        try {
            return server.getResourceToProject(projectId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new ArrayList<ResourceProject>();
    }
    /**
     * Method to delete a user to a project
     * @param projectId
     */
    public void deleteUserToProject(int projectId) {
        try {
            server.delteUsertoProject(projectId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method to delete a team
     * @param teamId
     */
    public void deleteTeam(int teamId) {
        try {
            server.deleteTeam(teamId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method to get all roles that a user have in a project
     * @param userId
     * @param projectId
     * @return
     */
    public ArrayList<String> getRoleToUserProject(int userId, int projectId) {
        try {
            return server.getRoleToUserProject(userId, projectId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new ArrayList<String>();
    }
    /**
     * Method to get all roles that a user have in a session
     * @param userId
     * @param sessionId
     * @return
     */
    public ArrayList<String> getRoleToUserSession(int userId, int sessionId) {
        try {
            return server.getRoleToUserSession(userId, sessionId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new ArrayList<String>();

    }
    /**
     * Method to register roles to a user
     * @param userId
     * @param rolles
     */
    public void registerRolesToUser(int userId, ArrayList<String> rolles) {
        try {
            server.registerRoleToUser(userId, rolles);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method that return all roles to a user
     * @param userId
     * @return
     */
    public ArrayList<String> getRolesToUser(int userId) {
        try {
            return server.getRoleToUser(userId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new ArrayList<String>();
    }
    /**
     * Method to update the sessionlist. used in callbeck
     */
    public void updateSessionList() {
        try {
            sessions = server.getAllSessionsToProject(selectedProject.getId());
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    public ArrayList<User> getProjectParticipans(int projectId){
        try {
            return server.getProjectParticipants(projectId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new ArrayList<User>();
    }


    /**
     * Method used when a project is seleceted, sessions and activitys are loaded
     * @param projectName
     */
    public void projectClicked(int projectId) {
        for (int i = 0; i < projects.size(); i++) {
            if (projects.get(i).getId() == projectId) {
                selectedProject = projects.get(i);
                gui.getChatPanel().clearTextAreaMainChat();
                break;
            }
        }
        try {
            activities = server.getAllActivities(selectedProject.getId());
            sessions = server.getAllSessionsToProject(selectedProject.getId());
            projectUsers = server.getProjectParticipants(selectedProject.getId());
            ArrayList<ChattLog> log = server.getChattLogToProject(selectedProject.getId());
            if (log.size() > 0) {
                if(log.size()==1) gui.getChatPanel().appendMoreLogToTextAreaMainChat(log.get(0).getChattLog());
                else{
                    for (int i = 0; i < log.size(); i++) {
                        if(i<log.size()-1)gui.getChatPanel().appendLogToTextAreaMainChat(log.get(i).getChattLog());
                        else gui.getChatPanel().appendMoreLogToTextAreaMainChat(log.get(i).getChattLog());
                    }
                }
            }
            server.connectChat(callback, clientIp);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Method that returns all projectLeaders
     * @return
     */
    /*public ArrayList<String> getAvailableLeaders() {
        ArrayList<String> leaderNames = new ArrayList<String>();

        try {
            availableProjectLeaders = server.getProjectLeader();
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }

        for (int i = 0; i < availableProjectLeaders.size(); i++) {
            leaderNames.add(availableProjectLeaders.get(i).getUsername());
        }


        return leaderNames;
    }
    /**
     * Method that get all users to a session
     * @param index
     * @return
     */

    public ArrayList<String> getAddedUsersToSession(int index) {
        ArrayList<String> addedExperts = new ArrayList<String>();
        try {
            for (int i = 0; i < server.getExpertsForSession(index).size(); i++) {
                addedExperts.add(server.getExpertsForSession(index).get(i).getUsername());
            }
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }

        return addedExperts;
    }
    /**
     * Method that return all users not selected to the selected project
     * @param projectId
     * @return
     */
    public ArrayList<String> getAvailableProjectUsers(int projectId) {
        ArrayList<String> availableProjectUsers = new ArrayList<String>();

        for (int i = 0; i < projectUsers.size(); i++) {
            availableProjectUsers.add(projectUsers.get(i).getUsername());
        }

        return availableProjectUsers;
    }

    /**
     * Method used to edit the decisonlist to a project
     * @param decisionList
     * @param projectId
     */
    public void editDecisionList(ArrayList<DecisionList> decisionList, int projectId) {
        try {
            server.editDecisionList(decisionList, projectId);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method used to register a new decision
     * @param decisionList
     */
    public void registerDecisionListItem(DecisionList decisionList) {
        try {
            server.registerDecisionList(decisionList);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void sendResourceUpdates() {
            try {
                server.sendResourceUpdates(callback);
            } catch (RemoteException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
        }


    public void sendActionlistUpdates() {
            try {
                server.sendActionlistUpdates(callback);
            } catch (RemoteException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    /**
     * Method used to notify other clients that a new decision is maid
     */
    public void sendDecisionListUpdates() {
        try {
            server.sendDecisionListUpdates(callback);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void updateResources() {
        gui.updateResources();
    }
    /**
     * Method to update the decisionList
     */
    public void updateDecisionList() {
        gui.updateDecisionList();
    }
    /**
     * Method to get all users
     * @return
     */
    public ArrayList<User> getAllUsers() {
        try {
            return server.getAllUsers();
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return new ArrayList<User>();
    }
    /**
     * Method used to update projectliste. used if someone else added a project
     */
    public void updateProjectList() {
        projectNames.clear();
        try {
            projects = server.getAllProjectsToUser(loginn.getUsername());

        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        for (int i = 0; i < projects.size(); i++) {
            projectNames.add(projects.get(i).getName());
        }
        gui.updateProjectList();
        gui.updateUserlistFrame();
    }
    /**
     * Method used to broadcast projects
     */
    public void sendProjectUpdates() {
        try {
            server.sendProjectUpdates(callback);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public void sendSessionUpdates() {
        try {
            server.sendSessionUpdates(callback);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }


    public void updateSessions() {
        gui.updateSessionPanels();
        gui.welcomeTabInsertData();
    }
    /**
     * Method used to broadcast the new chatt
     * @param text
     */
    public void sendMessage(String text) {
        try {
            server.broadcast(text, callback);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Method used to disconnect from server
     */
    public void disconnectFromServer() {
        try {
            System.out.println("Quit ble kallt i client.");
            server.quit(callback,clientIp);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
    /**
     * Getters and setters
     */


    public void setSelectedActivity(String activityName) {
        if (!activities.isEmpty()) {
            for (Activity a : activities) {
                if (a.getActivityName().equals(activityName)) {
                    selectedActivity = a;
                    break;
                }
            }
        }
    }

    public ArrayList<User> getUsersAddedToVoiceList(){
        ArrayList<User> addedVoiceListUsers = new ArrayList<User>();
        try {
           addedVoiceListUsers = server.getVoiceListUsers(selectedProject.getId());
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return addedVoiceListUsers;
    }

    public boolean isAdmin() {
        return admin;
    }
    
    public ArrayList<String> getProjectNames() {

        return projectNames;
    }

    public Login getLoginn() {
        return loginn;
    }

    public Project getSelectedProject() {
        return selectedProject;
    }

    public Activity getSelectedActivity() {
        return selectedActivity;
    }

    public String getSessionName(int index) {
        return sessions.get(index).getName();
    }

    public String getSessionDate(int index) {
        return sessions.get(index).getDate();
    }

    public String getSessionTime(int index) {
        return sessions.get(index).getStartTime();
    }

    public String getSessionPlace(int index) {
        return sessions.get(index).getPlace();
    }

    public String getActivityStartDate() {
        return selectedActivity.getStarteDate();
    }

    public String getActivityEndDate() {
        return selectedActivity.getEndDate();
    }

    public String getActivitiyResponsible() {
        return selectedActivity.getResponsible();
    }

    public String getActivityStatus() {
        return selectedActivity.getStatus();
    }

    public String getActivityDescription() {
        return selectedActivity.getDescription();
    }

    public String getActivityGoals() {
        return selectedActivity.getGoals();
    }

    public String getActivityPlace() {
        return selectedActivity.getLocation();
    }

    public Session getSelectedSession() {
        return selectedSession;
    }

    public int getSelectedSessionTab() {
        return selectedSessionTab;
    }

    public boolean isActivityOnActionList() {
        return selectedActivity.isOnActionList();
    }

    public ArrayList<Session> getSessions() {
        return sessions;
    }

    public int getNumberOfActivities() {
        return activities.size();
    }
    
    public boolean isLogginButton() {
        return logginButton;
    }

    public void setLogginButton(boolean logginButton) {
        this.logginButton = logginButton;
    }

    public ArrayList<User> getProjectUsers() {
        return projectUsers;
    }

    public Server getServer() {
        return server;
    }

    public void setServer(Server server) {
        this.server = server;
    }

    public Callback getCallback() {
        return callback;
    }

    public void setCallback(Callback callback) {
        this.callback = callback;
    }


    /**
     * Class userd to implements callback.
     */

    public void updateUserList() {
        gui.updateUserlistFrame();
    }

    public void updateVoiceList() {
        gui.updateVoiceList();
    }

    public void updateActionlist() {
        gui.updateActionList();
    }

    public void sendVoiceListUpdate(){
        try {
            server.sendVoiceListUpdates(callback);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void sendUserUpdates(){
        try {
            server.sendUserListUpdates(callback);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void sendActivityUpdates(){
        try{
            server.sendActivityUpdates(callback);
        } catch (RemoteException ex){
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public boolean validateTime(String time){
        if(time.trim().length()!=4)return false;
        for(int i=0; i<time.length();i++){
            if(!Character.isDigit(time.charAt(i)))return false;
        }
        return true;
    }

    public boolean validateDate(String dato){
        if(dato.length()!=10)return false;
        String temp = dato.replaceAll("-", "");
        if(temp.length()!=8)return false;
        for(int i=0; i<temp.length();i++){
            if(!Character.isDigit(temp.charAt(i))) return false;
        }
        return true;
    }

    public void sendCountDownStart(int min){
        try {
            server.sendCountDownStarts(callback, min);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void sendCountDownStop(){
        try {
            server.sendCountDownStops(callback);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void sendCountDownResume(){
        try {
            server.sendCountDownResumes(callback);
        } catch (RemoteException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void startCountDown(int min){
        gui.startCountDown(min);
    }
    
    public void stopCountDown(){
        gui.stopCountDown();
    }

    public void resumeCountDown(){
        gui.resumeCountDown();
    }

    public String getIp() {
        return ip;
    }

    public class CallbackImpl extends UnicastRemoteObject implements Callback {

        String userName;
        JTextArea area;
        int quizScore = 0;
        JTextArea pmArea;
        String fullName;
        /**
         * Empty constructor.
         * @throws RemoteException
         */
        public CallbackImpl() throws RemoteException {
        }

        


        public void cbUpdateProjectList() throws RemoteException{
            updateProjectList();
        }

        /**
         * Method used to update decisionlist
         * @throws RemoteException
         */
        public void cbUpdateDecisionList() throws RemoteException {
            updateDecisionList();
        }

        /**
         * Method used to update action list
         * @throws RemoteException
         */
        public void cbUpdateActionlist() throws RemoteException {
            updateActionlist();
        }

        /**
         * Method used to update activity list
         * @throws RemoteException
         */
        public void cbUpdateActivityList() throws RemoteException {
            updateActivityList();
        }

        /**
         * Method used update userlist
         * @throws RemoteException
         */
        public void cbUpdateUserList() throws RemoteException {
            updateUserList();
        }

        /*
         * Method used to update the voice list
         */
        public void cbUpdateVoiceList() throws RemoteException {
            updateVoiceList();
        }

        /**
         * Method used to start the countdown
         * @param min
         * @throws RemoteException
         */
        public void cbStartCountDown(int min) throws RemoteException {
            startCountDown(min);
        }

        /**
         * Method used to stop the countdown
         * @throws RemoteException
         */
        public void cbStopCountDown() throws RemoteException {
            stopCountDown();
        }

        /**
         * Method used to resume the countdown
         * @throws RemoteException
         */

        public void cbResumeCountDown() throws RemoteException {
            resumeCountDown();
        }

        /**
         * Method used to update the sessions
         * @throws RemoteException
         */
        public void cbUpdateSessions() throws RemoteException {
            updateSessions();
        }

        /**
         * Method used to update the resources
         * @throws RemoteException
         */
        public void cbUpdateResources() throws RemoteException {
            updateResources();
        }

        /**
         * A simple method that formats the clients local time into a suitable
         * timestamp string.
         * @return String
         */
        public String timestamp() {
            Date todaysDate = new Date();
            SimpleDateFormat formatter = new SimpleDateFormat("[HH:mm:ss] ");
            return formatter.format(todaysDate);
        }

        /**
         * This method prints a text to the main chat whenever a user connects to the chat.
         * @param userName
         * @throws RemoteException
         */
        public void connectMessage(String userName) throws RemoteException {
            if (area != null) {
                area.append(timestamp() + userName + " has connected.\n");
                gui.getChatPanel().getTextAreaMainChat().setCaretPosition(gui.getChatPanel().getTextAreaMainChat().getDocument().getLength());
            }
        }

        /**
         * This method prints all the messages that are being broadcasted to the main chat.
         * @param message
         * @param userName
         * @throws RemoteException
         */
        public void broadcastMessage(String message, String userName) throws RemoteException {
            if (area != null) {
                area.append(timestamp() + userName + " wrote: " + message + "\n");
                area.setCaretPosition(area.getDocument().getLength());
            }
        }

        /**
         * This method will print a text in the main chat that a user has left the chat. If a client is having a private
         * conversation with that person it will also print the text into that text area.
         * @param userName
         * @throws RemoteException
         */
        public void quitMessage(String userName) throws RemoteException {
            if (area != null) {
                area.append(timestamp() + userName + " has left the chat.\n");
            }
        }

        /**
         * This method gets the list of users. It will first be cleared and then users
         * will be added again to make sure that the clientList is always updated.
         * SwingUtilites.invokeLater() is used to make sure that the GUI updates the list
         * after all the users have been added.
         * @param userList
         * @throws RemoteException
         */
        public void getClientList(ArrayList<String> userList) throws RemoteException {
            gui.getChatPanel().getListModel().clear();
            for (int i = 0; i < userList.size(); i++) {
                String user = userList.get(i);
                gui.getChatPanel().getListModel().addElement(user);
            }
            SwingUtilities.invokeLater(new Runnable() {

                public void run() {
                    gui.getChatPanel().getUserList().updateUI();
                }
            });
        }

        /*
         * Getters and setters
         */
        public String getUserName() throws RemoteException {
            return userName;
        }

        public void setUserName(String userName) throws RemoteException {
            this.userName = userName;
        }

        public void setTextArea(javax.swing.JTextArea area) throws RemoteException {
            this.area = area;
        }

        public void setPmTextArea(javax.swing.JTextArea pmArea) throws RemoteException {
            this.pmArea = pmArea;
        }

        public Module.Project getSelectedProject() throws RemoteException {
            return selectedProject;
        }




    }
   
    
}
